package com.sann.demo001;

import com.sann.demo001.ioc.DowJonesNewsListener;
import com.sann.demo001.ioc.DowJonesNewsPersister;
import com.sann.demo001.ioc.FXNewsProvider;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

import java.io.Reader;

public class BeanFactoryTest2 {
    /**
     * BeanFactory的对象注册与依赖绑定方式
     * @param args
     */
    public static void main(String[] args) {
        // 方式一: 直接编码方式
        /*
        DefaultListableBeanFactory beanDefinitionRegistry = new DefaultListableBeanFactory();
        BeanFactory container = bindViaCode(beanDefinitionRegistry);
        FXNewsProvider provider = (FXNewsProvider) container.getBean("djNewsProvider");
        provider.getAndPersistNews();
        */
        // 方式二: 外部配置文件(这里以xml为例,properties格式配置文件不做介绍)
        DefaultListableBeanFactory beanDefinitionRegistry = new DefaultListableBeanFactory();
        BeanFactory container = bindViaXmlFile(beanDefinitionRegistry);
        FXNewsProvider newsProvider = (FXNewsProvider) container.getBean("djNewsProvider");
        newsProvider.getAndPersistNews();
    }

    public static BeanFactory bindViaCode(BeanDefinitionRegistry registry){
        // 根据字节码创建Bean,并进行封装
        AbstractBeanDefinition newsProvider = new RootBeanDefinition(FXNewsProvider.class);
        AbstractBeanDefinition newsListener = new RootBeanDefinition(DowJonesNewsListener.class);
        AbstractBeanDefinition newsPersister = new RootBeanDefinition(DowJonesNewsPersister.class);

        // Bean注册到容器中
        registry.registerBeanDefinition("djNewsProvider", newsProvider);
        registry.registerBeanDefinition("djNewsListener", newsListener);
        registry.registerBeanDefinition("djNewsPersister", newsPersister);

        // 指定依赖关系
        // 1.可以通过构造器方式注入
//        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
//        constructorArgumentValues.addIndexedArgumentValue(0,newsListener);
//        constructorArgumentValues.addIndexedArgumentValue(1, newsPersister);
//        newsProvider.setConstructorArgumentValues(constructorArgumentValues);

        // 2.或者通过setter方式注入
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        propertyValues.addPropertyValue("newsListener", newsListener);
        propertyValues.addPropertyValue("newsPersister",newsPersister);
        newsProvider.setPropertyValues(propertyValues);
        // 绑定完成
        return (BeanFactory) registry;
    }

    public static BeanFactory bindViaXmlFile(BeanDefinitionRegistry registry){
        XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(registry);
        xmlReader.loadBeanDefinitions("classpath:demo001/beanfactoryawareinject.xml");
        return (BeanFactory) registry;
    }
}
